﻿using DeskSharp.Properties;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

namespace DeskSharp
{
    public partial class Form1 : Form
    {
        static IntPtr s_hWndOldParent = IntPtr.Zero;
        Timer timer = new Timer();//窗体置顶
        Timer hoverTimer = new Timer();//鼠标悬停动画
        Timer normal_particleTimer = new Timer();//正常情况下动画
        List<Bitmap> hoverImgs = new List<Bitmap>();
        List<Bitmap> normal_particleImgs = new List<Bitmap>();

        public Form1()
        {
            InitializeComponent();
            Load += Form1_Load;
        }
        void CheckParent(IntPtr hWnd)
        {
            IntPtr hWndProgram = IntPtr.Zero;
            IntPtr hWndShellDLL = IntPtr.Zero;

            hWndProgram = Win32.FindWindow("Progman", "Program Manager");
            if (hWndProgram != IntPtr.Zero)
            {
                hWndShellDLL = Win32.FindWindowEx(hWndProgram, IntPtr.Zero, "SHELLDLL_DefView", null);
            }
            if (hWndShellDLL != IntPtr.Zero && s_hWndOldParent != hWndShellDLL)
            {
                Win32.SetWindowLong(hWnd, Win32.GWL_HWNDPARENT, hWndShellDLL);
                s_hWndOldParent = hWndShellDLL;
            }
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            SetBits(Resources.pendant_ani_normal__125);

            timer.Interval = 200;
            timer.Tick += Timer_Tick;
            timer.Enabled = true;
            int x = 0;
            int hoverMax = Resources.pendant_ani_hover__125.Width;
            do
            {
                hoverImgs.Add(crop(Resources.pendant_ani_hover__125, new Rectangle(x, 0, 100, 100)));
                normal_particleImgs.Add(UniteImage(100, 100, Resources.pendant_ani_normal__125, crop(Resources.pendant_ani_normal_particle__125, new Rectangle(x, 0, 100, 100))));
                x += 100;
            } while (x < hoverMax);


            normal_particleTimer.Interval = 1000 / 60;
            normal_particleTimer.Tick += Normal_particleTimer_Tick;
            normal_particleTimer.Enabled = true;

        }

        int particleTimerIndex = 0;
        private void Normal_particleTimer_Tick(object sender, EventArgs e)
        {
            if (particleTimerIndex >= normal_particleImgs.Count)
            {
                particleTimerIndex = 0;
            }
            SetBits(normal_particleImgs[particleTimerIndex]);
            particleTimerIndex++;
        }
        void SetDefault()
        {
            SetBits(Resources.pendant_ani_normal__125);
        }
        /// <summary>
        /// 裁切图片
        /// </summary>
        /// <param name="src"></param>
        /// <param name="cropRect"></param>
        /// <returns></returns>
        private Bitmap crop(Bitmap src, Rectangle cropRect)
        {
            //Rectangle cropRect = new Rectangle(0, 0, 400, 400);
            Bitmap target = new Bitmap(cropRect.Width, cropRect.Height);

            using (Graphics g = Graphics.FromImage(target))
            {
                g.DrawImage(src, new Rectangle(0, 0, target.Width, target.Height),
                      cropRect,
                      GraphicsUnit.Pixel);
            }
            return target;
        }
        /// <summary>
        /// 叠加图片
        /// </summary>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="img1"></param>
        /// <param name="img2"></param>
        /// <returns></returns>
        public Bitmap UniteImage(int width, int height, Image img1, Image img2)
        {
            var img = new Bitmap(width, height);

            Graphics g = Graphics.FromImage(img);

            g.Clear(Color.Transparent);

            g.DrawImage(img1, 0, 0, img1.Width, img1.Height);
            g.DrawImage(img2, 0, 0, img2.Width, img2.Height);

            return img;

        }
        private void Timer_Tick(object sender, EventArgs e)
        {
            CheckParent(this.Handle);
        }
        //记录鼠标按键是否按下
        private bool isMouseDown = false;

        bool haveHandle = false;

        private Point mPoint;

        private void InitializeStyles()
        {
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            SetStyle(ControlStyles.UserPaint, true);
            UpdateStyles();
        }
        protected override void OnClosing(CancelEventArgs e)
        {
            e.Cancel = true;
            base.OnClosing(e);
            haveHandle = false;
        }

        protected override void OnHandleCreated(EventArgs e)
        {
            InitializeStyles();
            base.OnHandleCreated(e);
            haveHandle = true;
        }
        protected override CreateParams CreateParams
        {
            get
            {
                CreateParams cParms = base.CreateParams;
                cParms.ExStyle |= 0x00080000; // WS_EX_LAYERED
                return cParms;
            }
        }

        public void SetBits(Bitmap bitmap)
        {
            if (!haveHandle) return;

            if (!Bitmap.IsCanonicalPixelFormat(bitmap.PixelFormat) || !Bitmap.IsAlphaPixelFormat(bitmap.PixelFormat))
                throw new ApplicationException("The picture must be 32bit picture with alpha channel.");
            System.Threading.Tasks.Task.Factory.StartNew(() =>
            {
                IntPtr oldBits = IntPtr.Zero;
                IntPtr screenDC = Win32.GetDC(IntPtr.Zero);
                IntPtr hBitmap = IntPtr.Zero;
                IntPtr memDc = Win32.CreateCompatibleDC(screenDC);

                try
                {
                    Win32.Point topLoc = new Win32.Point(Left, Top);
                    Size bitMapSize = new Size(bitmap.Width, bitmap.Height);
                    Win32.BLENDFUNCTION blendFunc = new Win32.BLENDFUNCTION();
                    Win32.Point srcLoc = new Win32.Point(0, 0);

                    hBitmap = bitmap.GetHbitmap(Color.FromArgb(0));
                    oldBits = Win32.SelectObject(memDc, hBitmap);

                    blendFunc.BlendOp = Win32.AC_SRC_OVER;
                    blendFunc.SourceConstantAlpha = 255;
                    blendFunc.AlphaFormat = Win32.AC_SRC_ALPHA;
                    blendFunc.BlendFlags = 0;
                    this.Invoke((EventHandler)delegate
                    {
                        Win32.UpdateLayeredWindow(Handle, screenDC, ref topLoc, ref bitMapSize, memDc, ref srcLoc, 0, ref blendFunc, Win32.ULW_ALPHA);
                    });
                }
                finally
                {
                    if (hBitmap != IntPtr.Zero)
                    {
                        Win32.SelectObject(memDc, oldBits);
                        Win32.DeleteObject(hBitmap);
                    }
                    Win32.ReleaseDC(IntPtr.Zero, screenDC);
                    Win32.DeleteDC(memDc);
                }
            });

        }

        /// <summary>
        /// 设置窗体具有鼠标穿透效果
        /// </summary>
        /// <param name="flag">true穿透，false不穿透</param>
        public void SetPenetrate(bool flag = true)
        {
            uint style = Win32.GetWindowLong(this.Handle, Win32.GWL_EXSTYLE);
            if (flag)
                Win32.SetWindowLong(this.Handle, Win32.GWL_EXSTYLE, style | Win32.WS_EX_TRANSPARENT | Win32.WS_EX_LAYERED);
            else
                Win32.SetWindowLong(this.Handle, Win32.GWL_EXSTYLE, style & ~(Win32.WS_EX_TRANSPARENT | Win32.WS_EX_LAYERED));
            Win32.SetLayeredWindowAttributes(this.Handle, 0, 100, Win32.LWA_ALPHA);
        }

        //退出
        private void tsmExit_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void Form1_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                isMouseDown = true;
                mPoint = new Point(e.X, e.Y);
            }
        }

        private void Form1_MouseUp(object sender, MouseEventArgs e)
        {
            //   修改鼠标状态isMouseDown的值 
            //   确保只有鼠标左键按下并移动时，才移动窗体 
            if (e.Button == MouseButtons.Left)
            {
                isMouseDown = false;
            }
        }

        private void Form1_MouseMove(object sender, MouseEventArgs e)
        {
            if (isMouseDown)
            {
                ////为当前应用程序释放鼠标捕获
                //Win32.ReleaseCapture();
                ////发送消息 让系统误以为在标题栏上按下鼠标
                //Win32.SendMessage((IntPtr)this.Handle, Win32.VM_NCLBUTTONDOWN, Win32.HTCAPTION, 0);
                if (e.Button == MouseButtons.Left)
                {
                    this.Location = new Point(this.Location.X + e.X - mPoint.X, this.Location.Y + e.Y - mPoint.Y);
                }
            }
        }
        int nowHoverIndex = 0;
        private void Form1_MouseEnter(object sender, EventArgs e)
        {
            normal_particleTimer.Tick -= Normal_particleTimer_Tick;
            nowHoverIndex = 0;
            hoverTimer = new Timer();
            hoverTimer.Tick += (tSender, tE) =>
            {
                if (nowHoverIndex >= hoverImgs.Count)
                {
                    nowHoverIndex = 0;
                }
                SetBits(hoverImgs[nowHoverIndex]);
                nowHoverIndex++;
            };
            hoverTimer.Interval = 1000 / 60;
            hoverTimer.Enabled = true;
        }

        private void Form1_MouseLeave(object sender, EventArgs e)
        {
            if (hoverTimer != null)
            {
                hoverTimer.Stop();
                hoverTimer.Enabled = false;
                hoverTimer.Dispose();
            }
            SetDefault();
            particleTimerIndex = 0;
            normal_particleTimer.Tick += Normal_particleTimer_Tick;
        }

        private void 退出ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }
    }
}
